package com.fsh.lingsp.common.chat.consumer;

import com.fsh.lingsp.common.chat.dao.ContactDao;
import com.fsh.lingsp.common.chat.dao.MessageDao;
import com.fsh.lingsp.common.chat.dao.RoomDao;
import com.fsh.lingsp.common.chat.dao.RoomFriendDao;
import com.fsh.lingsp.common.chat.domain.entity.Message;
import com.fsh.lingsp.common.chat.domain.entity.Room;
import com.fsh.lingsp.common.chat.domain.entity.RoomFriend;
import com.fsh.lingsp.common.chat.domain.enums.RoomTypeEnum;
import com.fsh.lingsp.common.chat.domain.vo.response.ChatMessageResp;
import com.fsh.lingsp.common.chat.service.ChatService;
import com.fsh.lingsp.common.chat.service.WeChatMsgOperationService;
import com.fsh.lingsp.common.chat.service.cache.GroupMemberCache;
import com.fsh.lingsp.common.chat.service.cache.HotRoomCache;
import com.fsh.lingsp.common.chat.service.cache.RoomCache;
import com.fsh.lingsp.common.common.constant.MQConstant;
import com.fsh.lingsp.common.common.domain.dto.MsgSendMessageDTO;
import com.fsh.lingsp.common.user.service.cache.UserCache;
import com.fsh.lingsp.common.user.service.impl.PushService;
import com.fsh.lingsp.common.websocket.adapter.WSAdapter;
import com.fsh.lingsp.common.websocket.service.WebSocketService;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * 作者：fsh
 * 日期：2024/03/14
 * <p>
 * 描述：
 * Description: 发送消息更新房间收信箱，并同步给房间成员信箱
 *
 * consumerGroup: 消费者组名。在 RocketMQ 中，消费者组是用来实现负载均衡和消息消费的并发处理的。
 * 同一消费者组内的消费者会共同消费同一个主题下的消息，但每条消息只会被该组内的一个消费者消费。
 *
 * topic是消息的逻辑分类，生产者和消费者都会指定特定的主题进行消息的发布和消费。"chat_send_msg";
 */
@RocketMQMessageListener(consumerGroup = MQConstant.SEND_MSG_GROUP, topic = MQConstant.SEND_MSG_TOPIC)
@Component
public class MsgSendConsumer implements RocketMQListener<MsgSendMessageDTO> {

    @Autowired
    private ChatService chatService;
    @Autowired
    private MessageDao messageDao;
    @Autowired
    WeChatMsgOperationService weChatMsgOperationService;
    @Autowired
    private RoomCache roomCache;
    @Autowired
    private RoomDao roomDao;
    @Autowired
    private GroupMemberCache groupMemberCache;
    @Autowired
    private RoomFriendDao roomFriendDao;
    @Autowired
    private ContactDao contactDao;
    @Autowired
    private HotRoomCache hotRoomCache;
    @Autowired
    private PushService pushService;

    /**
     * 定义一个接收消息的方法，参数是一个MsgSendMessageDTO类型的对象.
     * 消费 ：chat_send_msg 这个topic中的消息。
     *
     */
    @Override
    public void onMessage(MsgSendMessageDTO dto) {
        // 根据消息ID从数据库获取对应的消息对象
        Message message = messageDao.getById(dto.getMsgId());

        // 根据消息中的房间ID从缓存中获取对应的房间对象
        Room room = roomCache.get(message.getRoomId());

        // 调用chatService的getMsgResp方法，将消息对象和null作为参数，得到ChatMessageResp对象
        ChatMessageResp msgResp = chatService.getMsgResp2(message, null);

        // 更新房间的活动时间，使用roomDao的refreshActiveTime方法，传入房间ID、消息ID和消息创建时间
        //所有房间更新房间 最新消息 （最新消息id ，最新发消息时间）
        roomDao.refreshActiveTime(room.getId(), message.getId(), message.getCreateTime());

        // 从缓存中删除房间对象
        roomCache.delete(room.getId());

        // 判断房间是否为热门群聊
        if (room.isHotRoom()) {
            // 如果是热门群聊，则更新热门群聊的时间到redis缓存
            // 更新热门群聊时间-redis
            hotRoomCache.refreshActiveTime(room.getId(), message.getCreateTime());

            // 向所有在线的人推送消息
            // 推送所有人。 PUSH_TOPIC = "websocket_push";
            // 所以有个消费者 监听这个topic，将消息写给每个人的收件箱。
            pushService.sendPushMsg(WSAdapter.buildMsgSend(msgResp));
        } else {
            // 如果不是热门群聊，则初始化一个空的成员ID列表
            List<Long> memberUidList = new ArrayList<>();

            // 判断房间类型，如果是普通群聊，则从缓存中获取所有群成员的ID列表
            if (Objects.equals(room.getType(), RoomTypeEnum.GROUP.getType())) {
                memberUidList = groupMemberCache.getMemberUidList(room.getId());
            }
            // 如果房间类型是单聊，则从数据库中获取对应的单聊对象，并获取两个用户的ID作为成员列表
            else if (Objects.equals(room.getType(), RoomTypeEnum.FRIEND.getType())) {
                RoomFriend roomFriend = roomFriendDao.getByRoomId(room.getId());
                memberUidList = Arrays.asList(roomFriend.getUid1(), roomFriend.getUid2());
            }

            // 更新所有群成员的会话时间(最新一条消息的时间) ， 最新消息的id
            // 实际效果就是 每当群聊中有新消息，就更新这些字段。 前端的会话列表也能看见新消息来了。
            contactDao.refreshOrCreateActiveTime(room.getId(), memberUidList, message.getId(), message.getCreateTime());

            // 向房间(群聊或者单聊)成员推送消息
            pushService.sendPushMsg(WSAdapter.buildMsgSend(msgResp), memberUidList);
        }
    }


}
